package com.sduept.nwld.dataserver.controller.dataview;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import javax.annotation.PostConstruct;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.DualListModel;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import com.sduept.bigdata.document.core.CommonDocumentProperties;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.cim.model.core.Substation;
import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.extend.LineTower;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.cim.model.wires.DcLinesegment;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.manager.cim.LineTowerManager;
import com.sduept.nwld.dataserver.util.ExcelUtil;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.nwld.scriptengine.ExecuteScript;
import com.sduept.utils.GeographyDataUtil;
import com.sduept.utils.PingYinUtil;

@Named
@ViewScoped
public class LineTowerConfigController extends AbstractController {
	@Autowired
	private CommonDocumentProperties pros;
	private static final long serialVersionUID = -4569072736059956360L;
	@Autowired
	private CimManager cimManager;
	@Autowired
	private LineTowerManager ltm;
	@Autowired
	private MapDataCache cimCache;
	private TreeNode root;
	private TreeNode currentSelect;
	private String filterAcLineSegment;
	private List<LineTower> lineTowers;
	private LineTower lineTower;
	private List<LineTower> selectedTowers = new ArrayList<>();
	private LineTower selected;
	private String loopLineName;

	private List<ACLineSegment> aclinesegments;
	private List<DcLinesegment> dclinesegments;

	private DualListModel<String> aclines;
	private List<String> target = new ArrayList<String>();
	private String startStationName;
	private String endStationName;
	private LineSegment currentSelectLine;
	private int serialNo;
	private int loopSerialNo;
	private String loopLineno;
	private Float loopLineVoltage;
	List<LineTower> loopLineTowers = new ArrayList<LineTower>();
	String lineType = null;
	
	private StreamedContent file;
	
	@PostConstruct
	public void init() {
		root = new DefaultTreeNode();
		aclinesegments = cimManager.getAllAclines();
		List<String> source = new ArrayList<String>();
		for (ACLineSegment ac : aclinesegments) {
			source.add(ac.getName());
		}
		genAcLineTreeNode(aclinesegments, false);

		dclinesegments = cimManager.findAllDclineSegement();
		genDcLineTreeNode(dclinesegments, false);

		if (filterAcLineSegment != null && !"".equals(filterAcLineSegment)) {
			filterAcLineSegment = "";
		}
		aclines = new DualListModel<String>(source, target);
	}

	private void genAcLineTreeNode(List<ACLineSegment> roots, boolean lineExpand) {
		// 生成交流线路节点，并将交流线路根据电压等级排列
		DefaultTreeNode acline = new DefaultTreeNode("type", "交流线路", root);
		acline.setExpanded(true);

		List<Float> voltages = cimManager.listAllAcLineVoltage();
		List<TreeNode> vnodes = new ArrayList<>();
		for (Float v : voltages) {
			DefaultTreeNode vnode = new DefaultTreeNode("voltage", v.intValue() + "kV", acline);
			if (lineExpand) {
				vnode.setExpanded(true);
			}
			vnodes.add(vnode);
		}

		for (int i = 0; i < roots.size(); i++) {
			ACLineSegment line = roots.get(i);
			for (int j = 0; j < voltages.size(); j++) {
				if (voltages.get(j) - line.getStandVoltagelevel() == 0) {
					new LibTreeNode(ACLineSegment.class.getSimpleName(), line, vnodes.get(j));
					break;
				}
			}
		}

	}

	public void clearMapCache() {
		try {
			cimCache.reload();
		} catch (Exception e) {
			e.printStackTrace();
			alertErrorMessage("更新地图缓存失败:"+e.getMessage());
		}
		addSuccessMessage("更新地图缓存成功");
	}
	
	private void genDcLineTreeNode(List<DcLinesegment> roots, boolean lineExpand) {
		// 生成直流线路节点，并将交流线路根据电压等级排列
		DefaultTreeNode dcline = new DefaultTreeNode("type", "直流线路", root);
		dcline.setExpanded(true);

		List<Float> voltages = cimManager.listAllDcLineVoltage();
		List<TreeNode> vnodes = new ArrayList<>();
		for (Float v : voltages) {
			DefaultTreeNode vnode = new DefaultTreeNode("voltage", v.intValue() + "kV", dcline);
			if (lineExpand) {
				vnode.setExpanded(true);
			}
			vnodes.add(vnode);
		}

		for (int i = 0; i < roots.size(); i++) {
			DcLinesegment line = roots.get(i);
			for (int j = 0; j < voltages.size(); j++) {
				if (voltages.get(j) - line.getStandVoltagelevel() == 0) {
					new LibTreeNode(DcLinesegment.class.getSimpleName(), line,
							vnodes.get(j));
					break;
				}
			}
		}

	}

	public TreeNode getTreeNodeResource() {
		return root;
	}

	public void autoCompleteAcLineSegment(SelectEvent event) {
		Object item = event.getObject();
		if (null != item) {
			filterTree(item.toString());
		}
	}

	private void filterTree(String name) {
		root = new DefaultTreeNode();
		List<ACLineSegment> acs = cimManager.getAcLineSegmentsByName(name);
		genAcLineTreeNode(acs, true);
		List<DcLinesegment> dcs = cimManager.getDcLineSegmentsByName(name);
		genDcLineTreeNode(dcs, true);
	}

	// 事件
	public void onNodeSelect(NodeSelectEvent event) {
		currentSelect = event.getTreeNode();
		if (currentSelect != null) {
			if (ACLineSegment.class.getSimpleName().equals(currentSelect.getType())) {
				lineType = "ACLineSegment";
				currentSelectLine = (LineSegment)currentSelect.getData();
				ACLineSegment ac = ((ACLineSegment) currentSelect.getData());
				startStationName = StringUtils.isEmpty(ac.getStartStName()) ? "起始站" : ac.getStartStName();
				endStationName = StringUtils.isEmpty(ac.getEndStName()) ? "终点站" : ac.getEndStName();
				lineTowers = ltm.getAllLineTowerByLineId(ac.getId());
			} else if (DcLinesegment.class.getSimpleName().equals(currentSelect.getType())) {
				lineType = "DcLinesegment";
				currentSelectLine = (LineSegment)currentSelect.getData();
				DcLinesegment dc = ((DcLinesegment) currentSelect.getData());
				startStationName = StringUtils.isEmpty(dc.getStartStName()) ? "起始站" : dc.getStartStName();
				endStationName = StringUtils.isEmpty(dc.getEndStName()) ? "终点站" : dc.getEndStName();
				lineTowers = ltm.getAllLineTowerByLineId(dc.getId());
			}
		}
	}

	private void reloadMapGisLine(String lineId, String lineType, int isloop) {
		cimCache.reload();
	}
	
	public void preCreate() {
		if(lineTowers.size() != 0) {
			serialNo = lineTowers.size()-1;
		} else {
			serialNo = 1;
		}
		loopSerialNo = 0;
		lineTower = new LineTower();
		if (currentSelectLine != null) {
			lineTower.setLineName(currentSelectLine.getName());
			lineTower.setLineId(currentSelectLine.getId());
			Float f = currentSelectLine.getStandVoltagelevel();
			lineTower.setLineVoltage(f.intValue());
		}
	}
	
	public void saveNew() {
		if(!currentSelectLine.getName().equals(loopLineName)) {
			LineTower newLineTower = setNewLineTower(lineTower);
			if(newLineTower != null) {
				saveNewLineTower(newLineTower,lineTowers,currentSelectLine,1);
			} else {
				addErrorMessage("新建失败！");
				return;
			}
			reloadMapGisLine(currentSelectLine.getId(),lineType,newLineTower.getIsLoop());
			// 回路名称不为空
			if(!StringUtils.isEmpty(loopLineName)) {
				LineTower loopLineTower = setLoopLineTower(newLineTower);
				if(loopLineTower != null) {
					Collection<LineSegment> allLines = cimCache.getLineid_map().values();
					LineSegment loopLine = cimManager.getLineSegmentByName(loopLineName, allLines);
					saveNewLineTower(loopLineTower,loopLineTowers,loopLine,0);
				}
			}
		} else {
			 addErrorMessage("当前线路和回路不可为同一条线路");
		}
	}

	/**
	 * 保存杆塔信息
	 * @param lineTower
	 * @param lineTowers
	 * @param line
	 */
	public void saveNewLineTower(LineTower lineTower, List<LineTower> lineTowers, LineSegment line,int isShow) {
		if(lineTowers.size() != 0) {
			for (LineTower lt : lineTowers) {
				if(lt.getSerialno() == lineTower.getSerialno() || lt.getSerialno() > lineTower.getSerialno()) {
					lt.setSerialno(lt.getSerialno()+1);
					lineTowers.set(lineTowers.indexOf(lt), lt);
					ltm.createOrUpdate(lt);
				}
			}
			lineTower = ltm.createOrUpdate(lineTower);
			lineTowers.add(lineTower);
		} else {
			lineTower = ltm.createOrUpdate(lineTower);
			lineTowers.add(lineTower);
			int isLoop = loopLineName != null ? 1:0;
			createStartAndEndLineTower(lineTowers,line,isLoop,isShow);
		}
		getLineTowerDistance(lineTower);
		addSuccessMessage("保存成功");
		lineTower = null;
	}
	
	/**
	 * 设置新建的杆塔信息
	 * @param lineTower
	 * @return
	 */
	public LineTower setNewLineTower(LineTower lineTower) {
		lineTower.setUpdateType(0);
		if(serialNo == 0 || lineTowers.size() != 0 && serialNo > lineTowers.size()) {
			addErrorMessage("杆塔顺序号错误，保存失败！");
			return null;
		} else {
			lineTower.setSerialno(serialNo);
		}
		
		if(StringUtils.isEmpty(loopLineName)) {
			lineTower.setIsLoop(0);
			lineTower.setLoopCimName(null);
		} else {
			Collection<LineSegment> allLines = cimCache.getLineid_map().values();
			LineSegment loopLine = cimManager.getLineSegmentByName(loopLineName, allLines);
			lineTower.setLoopCimId(loopLine.getId());
			lineTower.setLoopCimName(loopLineName);
			lineTower.setIsLoop(1);
		}
		return lineTower;
	}
	/**
	 * 新建时，根据当前杆塔设置回路杆塔信息
	 * @param lineTower
	 * @return
	 */
	public LineTower setLoopLineTower(LineTower lineTower) {
		LineTower loopLineTower = new LineTower();
		
		if(loopSerialNo == 0 || loopLineTowers.size() != 0 && loopSerialNo > loopLineTowers.size()) {
			addErrorMessage("杆塔顺序号错误，保存失败！");
			return null;
		} else {
			loopLineTower.setSerialno(loopSerialNo);
		}
		loopLineTower.setIsLoop(1);
		loopLineTower.setIsShowInMap(0);//隐藏
		loopLineTower.setLatitude(lineTower.getLatitude());
		loopLineTower.setLongitude(lineTower.getLongitude());
		loopLineTower.setLineId(lineTower.getLoopCimId());
		loopLineTower.setLineName(lineTower.getLoopCimName());
		loopLineTower.setLineno(loopLineno);
		loopLineTower.setLineVoltage(loopLineVoltage.intValue());
		loopLineTower.setLoopCimId(lineTower.getLineId());
		loopLineTower.setLoopCimName(lineTower.getLineName());
		loopLineTower.setTowerno(lineTower.getTowerno());
		loopLineTower.setUpdateType(lineTower.getUpdateType());
		return loopLineTower;
	}
	
	public void preEdit() {
		if (selectedTowers.size() > 0) {
			selected = selectedTowers.get(0);
		} else {
			selected = null;
		}
	}
	
	public void saveEdit() {
		if (selected != null) {
			// 如果该杆塔为同杆塔，则同时修改其在回路中的杆塔信息
			if(selected.getIsLoop() == 1) {
				LineTower loopLineTower = getLoopLineTower(ltm.getLineTowerById(selected.getId()));
				loopLineTower.setTowerno(selected.getTowerno());
				loopLineTower.setLatitude(selected.getLatitude());
				loopLineTower.setLongitude(selected.getLongitude());
				loopLineTower.setIsShowInMap(selected.getIsShowInMap());
				loopLineTower.setUpdateType(1);
				loopLineTower = ltm.createOrUpdate(loopLineTower);
				getLineTowerDistance(loopLineTower);
			}
			selected.setUpdateType(1);
			selected = ltm.createOrUpdate(selected);
			getLineTowerDistance(selected);
			reloadMapGisLine(selected.getLineId(),lineType,selected.getIsLoop());
		}
		addSuccessMessage("保存成功");
		selected = null;
	}

	/**
	 * 1、selectedTowers.size() == lineTowers.size()
	 * 2、selectedTowers.size() == lineTowers.size()-2，&& 没有towerno==(-1)
	 * 3、selectedTowers.size() == lineTowers.size()-1，&& 仅有一个towerno==(-1)
	 * 这三种情况下，删除全部的杆塔信息
	 * @return
	 */
	public boolean ifDeleteAll() {
		int num = 0;
		for (LineTower lt : selectedTowers) {
			if("-1".equals(lt.getTowerno())) {
				num++;
			}
		}
		if((selectedTowers.size() == lineTowers.size()-1) && num == 1) {
			return true;
		} else if ((selectedTowers.size() == lineTowers.size()-2) && num == 0) {
			return true;
		} else if (selectedTowers.size() == lineTowers.size()) {
			return true;
		} else {
			return false;
		}
	}
	public void delete() {
		List<LineTower> loopLineTowers = new ArrayList<LineTower>();
		if(selectedTowers != null && currentSelect != null) {
			if (ifDeleteAll()) {
				String loopCimId = null;
				int isloop = 0;
				for (LineTower lineTower : lineTowers) {
					if(1 == lineTower.getIsLoop()) {
						isloop = 1;
					}
				}
				for (LineTower lineTower : lineTowers) {
					if((!"-1".equals(lineTower.getTowerno())) && !StringUtils.isEmpty(lineTower.getLoopCimId())) {
						loopCimId = lineTower.getLoopCimId();
						break;
					}
				}
				if(!StringUtils.isEmpty(loopCimId)) {
					loopLineTowers = ltm.getAllLineTowerByLineId(loopCimId);
				}
				// 此时，全部删除
				if(null != currentSelectLine){
					ltm.deleteTowersByLineId(currentSelectLine.getId());
				}
				try {
				} catch (Exception e) {
					e.printStackTrace();
					addErrorMessage("地图线路更新失败！");
				}
			} else {
				// 此时，删除所有选中的towerno!=(-1)的记录
				// 存储删除杆塔的sel
				List<Integer> deleteNoList = new ArrayList<Integer>();
				for (LineTower t : selectedTowers) {
					if(!"-1".equals(t.getTowerno())) {
						if(t.getIsLoop() == 1) {
							LineTower lt = getLoopLineTower(t);
							if(lt != null) {
								loopLineTowers.add(lt);
							}
						}
						deleteNoList.add(t.getSerialno());
						lineTowers.remove(t);
						ltm.delete(t.getId());
					}
				}
				for (LineTower tower : lineTowers) {
					int sum = 0;
					for (Integer i : deleteNoList) {
						if(tower.getSerialno() > i) {
							sum++;
						}
					}
					tower.setSerialno(tower.getSerialno()-sum);
					lineTowers.set(lineTowers.indexOf(tower), tower);
					ltm.createOrUpdate(tower);
				}
				setLineTowerOtherParameter(lineTowers);
				updateEndLineTowerSel(lineTowers);
				reloadMapGisLine(currentSelectLine.getId(),lineType,1);
			}
			lineTowers = ltm.getAllLineTowerByLineId(currentSelectLine.getId());
			addSuccessMessage("删除成功");
			selectedTowers.clear();
		}
	}
	
	// 同线路杆塔在一条线路中被删除，在另一条线路中重新设置回路信息
	public void updateLoopLineTowers(List<LineTower> looplineTowers) {
		if(looplineTowers.size() != 0) {
			for (LineTower lineTower : looplineTowers) {
				lineTower.setIsLoop(0);
				lineTower.setLoopCimId(null);
				lineTower.setLoopCimName(null);
				ltm.createOrUpdate(lineTower);
			}
		}
	}
	
	/**
	 * 根据当前杆塔，取得在回路中的同杆塔
	 * @param lineTower
	 * @return
	 */
	public LineTower getLoopLineTower(LineTower lineTower) {
		String loopLineId = lineTower.getLoopCimId();
		List<LineTower> lts = ltm.queryLoopLineTowers(loopLineId, lineTower.getLongitude(), lineTower.getLatitude(), lineTower.getTowerno());
		if(lts.size() != 0) {
			return lts.get(0);
		}
		return null;
	}
	
	/**
	 * 计算当前杆塔距离起始变电站、终止变电站、上一杆塔的距离，和下一杆塔“距离上一杆塔的距离”
	 */
	public void getLineTowerDistance(LineTower tower) {
		lineTowers = ltm.getAllLineTowerByLineId(tower.getLineId());
		DecimalFormat df = new DecimalFormat("#.##");
		LineTower startStation = lineTowers.get(0);
		LineTower endStation = lineTowers.get(lineTowers.size() - 1);
		if(!"-1".equals(tower.getTowerno())) {
			for (LineTower currentlineTower : lineTowers) {
				if(currentlineTower.getSerialno() == tower.getSerialno()) {
					int lastTowerSel = currentlineTower.getSerialno() - 1;
					LineTower lastTower = lineTowers.get(lastTowerSel);
					double distanceFromSS = generateDistancebetweenTwoPoints(currentlineTower, startStation);
					double distanceFromES = generateDistancebetweenTwoPoints(endStation,currentlineTower);
					double distanceFromLt = generateDistancebetweenTwoPoints(currentlineTower, lastTower);
					currentlineTower.setDistanceFromStartStation(Double.parseDouble(df.format(distanceFromSS)));
					currentlineTower.setDistanceFromEndStation(Double.parseDouble(df.format(distanceFromES)));
					currentlineTower.setDistanceFromLastTower(Double.parseDouble(df.format(distanceFromLt)));
					ltm.createOrUpdate(currentlineTower);
			} else if (currentlineTower.getSerialno()-1 == tower.getSerialno() && !"-1".equals(currentlineTower.getTowerno())) {
					double distanceFromLt = generateDistancebetweenTwoPoints(currentlineTower, tower);
					currentlineTower.setDistanceFromLastTower(Double.parseDouble(df.format(distanceFromLt)));
					ltm.createOrUpdate(currentlineTower);
				}
			}
		}
	}
	
	/**
	 * 删除成功后，修改最后一个杆塔（即终止变电站）的sel
	 * @param lineTowers
	 */
	public void updateEndLineTowerSel(List<LineTower> lineTowers) {
		for (LineTower tower : lineTowers) {
			if(tower.getSerialno()>0 && ("-1").equals(tower.getTowerno())) {
				tower.setSerialno(lineTowers.size()-1);
				lineTowers.set(lineTowers.indexOf(tower), tower);
				ltm.createOrUpdate(tower);
			}
		}
	}

	public void onTowerSelect(AjaxBehaviorEvent event) {
	}
	
	private double generateDistancebetweenTwoPoints(LineTower currentTower,LineTower lastTower) {
		if (currentTower != null && lastTower != null) {
			/**
			 * TODO 有时会有精度问题，渲染不规整
			 */
			// LonLatUtils.getDistance(currentTower.getLongitude(),
			// currentTower.getLatitude(), lastTower.getLongitude(),
			// lastTower.getLatitude());
			ExecuteScript executeScript = new ExecuteScript();
			if (currentTower.getLatitude() != null && currentTower.getLongitude() != null) {
				if (lastTower.getLatitude() != null && lastTower.getLongitude() != null) {
					return executeScript.getGreatCircleDistance(currentTower.getLatitude(),currentTower.getLongitude(),lastTower.getLatitude(), lastTower.getLongitude());
				}
			}
		}
		return 0d;
	}

	/**
	 * 模板下载
	 */
	public void fileDownloadView() {
		InputStream stream = null;
		try {
			stream = new FileInputStream(new File(pros.getTempletePath() + "lineTower.xlsx"));
			file = new DefaultStreamedContent(stream, "xlsx","lineTowerTemplet.xlsx");
		} catch (FileNotFoundException e) {
			addErrorMessage("文件下载失败，请联系技术人员！");
			e.printStackTrace();
		}
	}

	/**
	 * 根据线路编号顺序号和杆塔名称进行排序
	 * @param objs
	 * @return
	 */
	public List<List<Object>> sortByLinenoOrderAndTowerno(List<List<Object>> objs) {
		Collections.sort(objs, new Comparator<List<Object>>(){
			int cr = 0;
			int comp = 0;
			@Override
			public int compare(List<Object> o1, List<Object> o2) {
				int lineorder1 = Integer.parseInt(o1.get(5).toString());
				int lineorder2 = Integer.parseInt(o2.get(5).toString());
				comp = lineorder1 - lineorder2;
				// 按线路编号顺序号升序排序
				if(comp != 0) {
					cr = (comp > 0) ? 3 : -1;
				} else {
					// 按照towerno升序排序
					String towerNo1 = formatTowerNo(o1.get(0).toString());
					Double db_towerNo1 = Double.parseDouble(towerNo1);
					String towerNo2 = formatTowerNo(o2.get(0).toString());
					Double db_towerNo2 = Double.parseDouble(towerNo2);
					comp = db_towerNo1.compareTo(db_towerNo2);
					if (comp != 0) {
						cr = (comp > 0) ? 1 : -3;
					}
				}
				return cr;
			}
		});
		return objs;
	}
	
	/**
	 * 根据线路编号顺序号和杆塔sel进行排序
	 * @param objs
	 * @return
	 */
	public List<List<Object>> sortByLinenoOrderAndSel(List<List<Object>> objs) {
		Collections.sort(objs, new Comparator<List<Object>>(){
			int cr = 0;
			int comp = 0;
			@Override
			public int compare(List<Object> o1, List<Object> o2) {
				int lineorder1 = Integer.parseInt(o1.get(5).toString());
				int lineorder2 = Integer.parseInt(o2.get(5).toString());
				comp = lineorder1 - lineorder2;
				// 按线路编号顺序号升序排序
				if(comp != 0) {
					cr = (comp > 0) ? 3 : -1;
				} else {
					int selorder1 = Integer.parseInt(o1.get(3).toString());
					int selorder2 = Integer.parseInt(o2.get(3).toString());
					comp = selorder1 - selorder2;
					// 按照sel升序排序
					if (comp != 0) {
						cr = (comp > 0) ? 2 : -2;
					}
				} 
				return cr;
			}
		});
		return objs;
	}
	
	public void setUploadLineTower(LineTower lineTower,List<Object> list) {
		String towerNo = list.get(0).toString();
		lineTower.setTowerno(towerNo);
		lineTower.setLongitude(Double.parseDouble(list.get(1).toString()));
		lineTower.setLatitude(Double.parseDouble(list.get(2).toString()));
		lineTower.setUpdateType(1);
		lineTower.setIsShowInMap(1);
	}
	
	/**
	 * 文件上传
	 */
	public void handleFileUpload(FileUploadEvent event) {
		try {
			if(null != currentSelectLine){
				//删除CIM杆塔
				ltm.deleteTowersByLineId(currentSelectLine.getId());
			}
			List<List<Object>> objs = ExcelUtil.readExcelDefine(event.getFile().getInputstream(),2);
			List<LineTower> tempList = new ArrayList<LineTower>();
			Map<Double, LineTower> selSort = new HashMap<Double, LineTower>();
			TreeSet<Double> selSortSet = new TreeSet<Double>();
			StringBuffer errorsb = new StringBuffer();
			// towerno  longitude   latitude    sel           lineno       linenoOrder
			// 杆塔名称 0        经度 1                   纬度 2               整体线路顺序号 3      所属线段编号4       线段编号顺序号5
			int maxLength = objs.get(0).size();
			if(maxLength == 6) {
				addErrorMessage("当线段编号不为空时，线段编号顺序号必填！");
				return;
			}
			if(maxLength == 4) {
				// 根据杆塔名称排序
				int rowNo = 0;
				for (List<Object> list : objs) {
					rowNo++;
					LineTower lineTower = new LineTower();
					setUploadLineTower(lineTower,list);
					
					String towerNo = formatTowerNo(list.get(0).toString());
					Double db_towerNo = 0.0d;
					try {
						db_towerNo = Double.parseDouble(towerNo);
						selSort.put(db_towerNo, lineTower);
						selSortSet.add(db_towerNo);
					} catch (NumberFormatException e) {
						errorsb.append("第"+rowNo+"行("+towerNo+")");
						errorsb.append(" ");
					}
				}
			} else if (maxLength == 5) {
				// 根据sel排序杆塔
				for (List<Object> list : objs) {
					LineTower lineTower = new LineTower();
					setUploadLineTower(lineTower,list);
					
					Double db_towerNo = Double.parseDouble(list.get(3).toString());
					selSort.put(db_towerNo, lineTower);
					selSortSet.add(db_towerNo);
				}
			} else if (maxLength == 7) {
				// 有线路编号顺序号，进行排序
				List<List<Object>> orderObjs = new ArrayList<List<Object>>();
				String sel = objs.get(0).get(3).toString();
				if(!StringUtils.isEmpty(sel)) {
					orderObjs = sortByLinenoOrderAndSel(objs);
				} else {
					int rowNo = 0;
					// sel为空时，需要根据towerNo进行排序，将不符合规范的towerNo添加错误提醒，将符合规范的towerNo加入到tempObjs中
					List<List<Object>> tempObjs = new ArrayList<List<Object>>();
					for (List<Object> list : objs) {
						rowNo++;
						String towerNo = formatTowerNo(list.get(0).toString());
						try {
							Double.parseDouble(towerNo);
							tempObjs.add(list);
						} catch (NumberFormatException e) {
							errorsb.append("第"+rowNo+"行("+towerNo+")");
							errorsb.append(" ");
						}
					}
					orderObjs = sortByLinenoOrderAndTowerno(tempObjs);
				}
				Double order = 0.0d;
				for (List<Object> list : orderObjs) {
					order++;
					LineTower lineTower = new LineTower();
					setUploadLineTower(lineTower,list);
					
					lineTower.setLineno(list.get(4).toString());
					selSort.put(order, lineTower);
					selSortSet.add(order);
				}
			}
			// 将构造好的selSort添加到tempList中
			if (selSortSet.size() != 0) {
				for (Double s : selSortSet) {
					LineTower lt = selSort.get(s);
					tempList.add(lt);
				}
			}
			int isloop = 0;
			// 生成当前线路的杆塔信息
			genCurrentLineTowers(tempList);
			if(loopLineName != null && !loopLineName.equals(currentSelectLine.getName())) {
				// 生成回线的杆塔信息
				genLoopLineTowers(tempList);
				isloop = 1;
			}
			addSuccessMessage("文件上传成功！");
			if(errorsb.length() > 0) {
				alertErrorMessage("文件"+errorsb+"数据错误，只能包含数字和+、-、_ ，解析失败！");
			}
			lineTowers = ltm.getAllLineTowerByLineId(currentSelectLine.getId());
			reloadMapGisLine(currentSelectLine.getId(),lineType,isloop);
		} catch (IOException e1) {
			e1.printStackTrace();
			addErrorMessage("文件解析失败，请先下载模板！");
			return;
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("导入失败");

		}
	}
	// 生成当前线路的杆塔信息
	public void genCurrentLineTowers(List<LineTower> temp) {
		List<LineTower> lineTowers = new ArrayList<LineTower>();
		int isLoop = 0;
		String loopLineId = null;
		if(loopLineName != null) {
			isLoop = 1;
			Collection<LineSegment> allLines = cimCache.getLineid_map().values();
			LineSegment loopLine = cimManager.getLineSegmentByName(loopLineName, allLines);
			loopLineId = loopLine.getId();
		}
		Float f = currentSelectLine.getStandVoltagelevel();
		if(temp.size()!=0) {
			int i = 0;
			for (LineTower lt : temp) {
				i++;
				lt.setSerialno(i);
				lt.setIsShowInMap(1);
				lt.setIsLoop(isLoop);
				lt.setLoopCimName(loopLineName);
				lt.setLoopCimId(loopLineId);
				lt.setLineId(currentSelectLine.getId());
				lt.setLineName(currentSelectLine.getName());
				lt.setLineVoltage(f.intValue());
				lt = ltm.createOrUpdate(lt);
				lineTowers.add(lt);
			}
		}
		createStartAndEndLineTower(lineTowers, currentSelectLine,isLoop,1);
		setLineTowerOtherParameter(lineTowers);
	}
	// 生成回线的杆塔信息
	public void genLoopLineTowers(List<LineTower> temp) {
		// 回路作为当前线路使用
		Collection<LineSegment> allLines = cimCache.getLineid_map().values();
		LineSegment loopline = cimManager.getLineSegmentByName(loopLineName, allLines);
		Float f = loopline.getStandVoltagelevel();
		// 首先删除该条线路上的所有杆塔信息（CIM）
		ltm.deleteTowersByLineId(loopline.getId());
		List<LineTower> lineTowers = new ArrayList<LineTower>();
		// 当前选中的路线作为回路
		if(temp.size()!=0) {
			int i = 0;
			for (LineTower lt : temp) {
				i++;
				lt.setSerialno(i);
				lt.setIsLoop(1);
				lt.setLoopCimName(currentSelectLine.getName());
				lt.setLoopCimId(currentSelectLine.getId());
				lt.setLineId(loopline.getId());
				lt.setLineName(loopLineName);
				lt.setLineVoltage(f.intValue());
				lt.setIsShowInMap(0);
				lt = ltm.createOrUpdate(lt);
				lineTowers.add(lt);
			}
		}
		createStartAndEndLineTower(lineTowers, loopline,1,0);
		setLineTowerOtherParameter(lineTowers);
	}
	
	public String formatTowerNo(String towerNo) {
		if (towerNo.contains("+")) {
			towerNo = towerNo.replace("+", ".");
		} else if (towerNo.contains("-")) {
			towerNo = towerNo.replace("-", ".");
		} else if (towerNo.contains("_")) {
			towerNo = towerNo.replace("_", ".");
		}
		return towerNo;
	}
	
	/**
	 * 根据线路起止变电站，生成该条线路的第0号和最后一个杆塔信息
	 * @param lineTowers
	 * @param line
	 * @param isLoop 是否有回路
	 * @param isShow 是否显示
	 */
	public void createStartAndEndLineTower(List<LineTower> lineTowers, LineSegment line,int isLoop,int isShow) {
		Float f = line.getStandVoltagelevel();
		LineTower firstT = lineTowers.get(0);
		LineTower endT = lineTowers.get(lineTowers.size()-1);
		// 起始变电站
		Substation startSubStation = cimManager.getStationById(line.getStartST());
		Double st_first = null; // 第一个杆塔距离起始变电站的距离
		Double st_last = null;  // 最后一个杆塔距离起始变电站的距离
		if(null!=startSubStation && null != startSubStation.getLongitude() && null != startSubStation.getLatitude()) {
			st_first = GeographyDataUtil.getDistance(startSubStation.getLongitude(), startSubStation.getLatitude(), firstT.getLongitude(), firstT.getLatitude());
			st_last = GeographyDataUtil.getDistance(startSubStation.getLongitude(), startSubStation.getLatitude(), endT.getLongitude(), endT.getLatitude());
		}
		// 终止变电站
		Substation endSubStation = cimManager.getStationById(line.getEndST());
		Double ed_first = null; // 第一个杆塔距离终止变电站的距离
		Double ed_last = null;  // 最后一个杆塔距离终止变电站的距离
		if(null != endSubStation && null != endSubStation.getLongitude() && null != endSubStation.getLatitude()) {
			ed_first = GeographyDataUtil.getDistance(endSubStation.getLongitude(), endSubStation.getLatitude(), firstT.getLongitude(), firstT.getLatitude());
			ed_last = GeographyDataUtil.getDistance(endSubStation.getLongitude(), endSubStation.getLatitude(), endT.getLongitude(), endT.getLatitude());
		}
		
		LineTower firstVirtualTower = new LineTower();
		firstVirtualTower.setTowerno("-1");
		firstVirtualTower.setUpdateType(1);
		firstVirtualTower.setLineId(line.getId());
		firstVirtualTower.setLineName(line.getName());
		firstVirtualTower.setLineVoltage(f.intValue());
		firstVirtualTower.setIsShowInMap(isShow);
		firstVirtualTower.setIsLoop(isLoop);
		firstVirtualTower.setLoopCimId(firstT.getLoopCimId());
		firstVirtualTower.setLoopCimName(firstT.getLoopCimName());
		
		LineTower endVirtualTower = new LineTower();
		endVirtualTower.setTowerno("-1");
		endVirtualTower.setUpdateType(1);
		endVirtualTower.setLineId(line.getId());
		endVirtualTower.setLineName(line.getName());
		endVirtualTower.setLineVoltage(f.intValue());
		endVirtualTower.setIsShowInMap(isShow);
		endVirtualTower.setIsLoop(isLoop);
		endVirtualTower.setLoopCimId(firstT.getLoopCimId());
		endVirtualTower.setLoopCimName(firstT.getLoopCimName());
		
		/**
		 * 找到这四个距离中最小的，确定第0号杆塔是起止变电站还是终止变电站
		 * min=0,第一个杆塔距离起始变电站的距离最小，起始变电站作为第0号杆塔
		 * min=1,第一个杆塔距离终止变电站的距离最小，终止变电站作为第0号杆塔
		 * min=2,最后一个杆塔距离起始变电站的距离最小，终止变电站作为第0号杆塔
		 * min=3,最后一个杆塔距离终止变电站的距离最小，起始变电站作为第0号杆塔
		 */
		int min = getMinPostion(new Double[]{st_first,ed_first,st_last,ed_last});
		Double firstLon = null;
		Double firstLat = null;
		Double endLon = null;
		Double endLat = null;
		if(min != -1){
			if(min == 0 || min == 3){
				if(null != startSubStation) {
					firstLat = startSubStation.getLatitude();
					firstLon = startSubStation.getLongitude();
				}
				if(null != endSubStation) {
					endLat = endSubStation.getLatitude();
					endLon = endSubStation.getLongitude();
				}
				
				firstVirtualTower.setSerialno(0);
				lineTowers.add(0, firstVirtualTower);
				
				endVirtualTower.setSerialno(endT.getSerialno()+1);
				lineTowers.add(endVirtualTower);
			} else {
				if(null != endSubStation) {
					firstLat = endSubStation.getLatitude();
					firstLon = endSubStation.getLongitude();
				}
				if(null != startSubStation) {
					endLat = startSubStation.getLatitude();
					endLon = startSubStation.getLongitude();
				}
				endVirtualTower.setSerialno(0);
				lineTowers.add(0,endVirtualTower);
				
				firstVirtualTower.setSerialno(endT.getSerialno()+1);
				lineTowers.add(firstVirtualTower);
			}
		}
	
		firstVirtualTower.setLatitude(firstLat);
		firstVirtualTower.setLongitude(firstLon);
		firstVirtualTower = ltm.createOrUpdate(firstVirtualTower);
		
		endVirtualTower.setLatitude(endLat);
		endVirtualTower.setLongitude(endLon);
		endVirtualTower = ltm.createOrUpdate(endVirtualTower);
	}
	
	private static int getMinPostion(Double[] ds) {
		double min = Double.MAX_VALUE;
		int pos = -1;
		for (int i = 0; i < ds.length; i++) {
			if(ds[i] != null && ds[i] < min){
				min = ds[i];
				pos = i;
			}
		}
		return pos;
	}
	
	/**
	 * 批量导入杆塔信息后，设置杆塔的其他参数信息,
	 * DistanceFromStartStation,DistanceFromEndStation,DistanceFromLastTower
	 */
	public void setLineTowerOtherParameter(List<LineTower> lineTowers) {
		DecimalFormat df = new DecimalFormat("#.##");
		double distanceFromSS = 0.0d; // 距离起始站的距离
		double distanceFromES = 0.0d; // 距离终点站的距离
		double distanceFromLt = 0.0d; // 当前杆塔距离上一个杆塔的距离
		LineTower startStation = lineTowers.get(0);
		int len = lineTowers.size();
		LineTower endStation = lineTowers.get(len - 1);
		LineTower lastTower = new LineTower();
		for (LineTower currentlineTower : lineTowers) {
			if(!("-1".equals(currentlineTower.getTowerno()))) {
				distanceFromSS = generateDistancebetweenTwoPoints(currentlineTower, startStation);
				distanceFromES = generateDistancebetweenTwoPoints(endStation,currentlineTower);
				currentlineTower.setDistanceFromStartStation(Double.parseDouble(df.format(distanceFromSS)));
				currentlineTower.setDistanceFromEndStation(Double.parseDouble(df.format(distanceFromES)));
				int sel = currentlineTower.getSerialno() - 1;
				if(sel>0 ||sel==0) {
					lastTower = lineTowers.get(sel);
					distanceFromLt = generateDistancebetweenTwoPoints(currentlineTower, lastTower);
					currentlineTower.setDistanceFromLastTower(Double.parseDouble(df.format(distanceFromLt)));
				}
				ltm.createOrUpdate(currentlineTower);
			}
		}
	}

	/**
	 * 如果是起止站，显示起止站名称，否则显示杆塔号
	 * @param lineTower
	 * @return
	 */
	public String showTowerNo(LineTower lineTower) {
		if(lineTower.getSerialno() == 0 && "-1".equals(lineTower.getTowerno())) {
			return startStationName;
		} else if (lineTower.getSerialno() > 0 && "-1".equals(lineTower.getTowerno())) {
			return endStationName;
		} else {
			return lineTower.getTowerno();
		}
	}
	
	public List<String> completeLineName(String query) {
		List<String> allLineNames = new ArrayList<String>();
		Collection<LineSegment> allLines = cimCache.getLineid_map().values();
        for (LineSegment line : allLines) {
        	allLineNames.add(line.getName());
        }
        List<String> qualifiedLineNames = new ArrayList<String>();
        for (String string : allLineNames) {
        	String pName = PingYinUtil.getPingYinHeader(string);
        	if (pName.contains(query)) {
        		qualifiedLineNames.add(string);
			}
		}
        return qualifiedLineNames;
    }
    
	public void getSelectLoopLineName(SelectEvent event){
		Object item = event.getObject();
		if(null != item){
			loopLineName = item.toString();
		}
		// 根据loopLineName获得loopSerialNo
		genLoopSerialNo(loopLineName);
	}
	
	// 根据loopLineName获得loopSerialNo
	public void genLoopSerialNo(String loopLineName) {
		Collection<LineSegment> allLines = cimCache.getLineid_map().values();
		LineSegment loopLine = cimManager.getLineSegmentByName(loopLineName, allLines);
		loopLineVoltage = loopLine.getStandVoltagelevel();
		loopLineTowers = ltm.getAllLineTowerByLineId(loopLine.getId());
		if(loopLineTowers.size() == 0) {
			loopSerialNo = 1;
		} else {
			loopSerialNo = loopLineTowers.size() - 1;
		}
	}
	
	public void exportLineTower() {
		ltm.exportExcel(lineTowers,currentSelectLine);
		String exportDir = pros.getExportTempPath();
		InputStream stream = null;
		try {
			stream = new FileInputStream(new File(exportDir + "LineTower.xlsx"));
			file = new DefaultStreamedContent(stream, exportDir, "LineTower.xlsx");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void initLoopLineName() {
		loopLineName = null;
	}
	
	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public String getFilterAcLineSegment() {
		return filterAcLineSegment;
	}

	public void setFilterAcLineSegment(String filterAcLineSegment) {
		this.filterAcLineSegment = filterAcLineSegment;
	}

	public TreeNode getCurrentSelect() {
		return currentSelect;
	}

	public void setCurrentSelect(TreeNode currentSelect) {
		this.currentSelect = currentSelect;
	}

	public List<LineTower> getLineTowers() {
		return lineTowers;
	}

	public void setLineTowers(List<LineTower> lineTowers) {
		this.lineTowers = lineTowers;
	}

	public LineTower getLineTower() {
		return lineTower;
	}

	public void setLineTower(LineTower lineTower) {
		this.lineTower = lineTower;
	}

	public List<LineTower> getSelectedTowers() {
		return selectedTowers;
	}

	public void setSelectedTowers(List<LineTower> selectedTowers) {
		this.selectedTowers = selectedTowers;
	}

	public List<DcLinesegment> getDclinesegments() {
		return dclinesegments;
	}

	public void setDclinesegments(List<DcLinesegment> dclinesegments) {
		this.dclinesegments = dclinesegments;
	}

	public List<ACLineSegment> getAclinesegments() {
		return aclinesegments;
	}

	public void setAclinesegments(List<ACLineSegment> aclinesegments) {
		this.aclinesegments = aclinesegments;
	}

	public DualListModel<String> getAclines() {
		return aclines;
	}

	public void setAclines(DualListModel<String> aclines) {
		this.aclines = aclines;
	}

	public List<String> getTarget() {
		return target;
	}

	public void setTarget(List<String> target) {
		this.target = target;
	}

	public String getStartStationName() {
		return startStationName;
	}

	public void setStartStationName(String startStationName) {
		this.startStationName = startStationName;
	}

	public String getEndStationName() {
		return endStationName;
	}

	public void setEndStationName(String endStationName) {
		this.endStationName = endStationName;
	}

	public LineTower getSelected() {
		return selected;
	}

	public void setSelected(LineTower selected) {
		this.selected = selected;
	}

	public int getSerialNo() {
		return serialNo;
	}

	public void setSerialNo(int serialNo) {
		this.serialNo = serialNo;
	}

	public String getLoopLineName() {
		return loopLineName;
	}

	public void setLoopLineName(String loopLineName) {
		this.loopLineName = loopLineName;
	}

	public int getLoopSerialNo() {
		return loopSerialNo;
	}

	public void setLoopSerialNo(int loopSerialNo) {
		this.loopSerialNo = loopSerialNo;
	}

	public String getLoopLineno() {
		return loopLineno;
	}

	public void setLoopLineno(String loopLineno) {
		this.loopLineno = loopLineno;
	}

	public StreamedContent getFile() {
		return file;
	}

	public void setFile(StreamedContent file) {
		this.file = file;
	}

}
